﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace XTYAPI.PLC
{
    /// <summary>
    /// 加减计数器
    /// WangdDong QQ851879790
    /// 使用“加减计数”指令递增和递减 CV 参数的计数器值。如果参数 CU 的信号状态从“0”变为“1”（信号上升沿），则参数 CV 的当前计数器值加 1。
    /// 如果参数 CD 的信号状态从“0”变为“1”（信号上升沿），则参数 CV 的计数器值减 1。如果在一个程序周期内输入 CU 和 CD 都出现了一个信号上升沿，则参数 CV 的当前计数器值保持不变。
    /// 计数器值达到参数 CV 指定数据类型的上限后，停止递增。达到上限后，即使出现信号上升沿，计数器值也不再递增。达到指定数据类型的下限后，计数器值便不再递减。
    /// 当参数 LD 中的信号状态变为“1”时，参数 CV 的计数器值会设置为参数 PV 的值。只要参数 LD 的信号状态为“1”，参数 CU 和 CD 的信号状态就不会影响该指令。
    /// 当 R 参数的信号状态变为“1”时，计数器值将置位为 0。只要 R 参数的信号状态仍为“1”，参数 CU、CD 和 LD 信号状态的改变就不会影响“加减计数”指令。
    /// 可以在 QU 参数中查询加计数器的状态。如果当前计数器值大于或等于参数 PV 的值，则参数 QU 的信号状态将置位为“1”。在其它任何情况下，参数 QU 的信号状态均为“0”。也可以为参数 PV 指定一个常数。
    /// 可以在 QD 参数中查询减计数器的状态。如果当前计数器值小于或等于“0”，则参数 QD 的信号状态将置位为“1”。在其它任何情况下，参数 QD 的信号状态均为“0”。
    /// </summary>
    public class CTUD
    {
        public CTUD()
        {
        }
        public CTUD(int pv) : this()
        {
            this.PV = pv;
        }
        bool cu,cd,r,ld, last;
        /// <summary>
        /// 溢出
        /// </summary>
        public bool Spill { get; set; } = true;
        /// <summary>
        /// 加数输入
        /// </summary>
        public bool CU
        {
            get
            {
                return cu;
            }
            set
            {
                if (value && !last)
                {
                    if (CV < PV)
                    {
                        CV++;
                    }
                    else
                    {
                        if (Spill)
                        {
                            CV++;
                        }
                        else
                        {
                            CV = PV;
                        }
                    }
                    QU = CV >= PV;
                }
                cu = last = value;
            }
        }
        /// <summary>
        /// 减数输入
        /// </summary>
        public bool CD
        {
            get
            {         
                return cd;
            }
            set
            {

                if (value && !last)
                {
                    if (CV > 0)
                    {
                        CV--;
                    }
                    else
                    {
                        if (Spill)
                        {
                            CV--;
                        }
                        else
                        {
                            CV = 0;
                        }
                    }                 
                }
                QD = CV <= 0;
                cd = last = value;
            }
        }
        /// <summary>
        /// 置位输出 CV 的目标值
        /// </summary>
        public bool LD
        {
            get { return ld; }
            set
            {
                if (value)
                {
                    CV = PV;
                }
                ld = value;
            }
        }
        /// <summary>
        /// 复位输入
        /// </summary>
        public bool R
        {
            get { return r; }
            set
            {
                if (value)
                {
                    CV = 0;
                }
                r = value;
            }
        }
        /// <summary>
        /// 置位输出 Q 的目标值
        /// </summary>
        public int PV { get; set; }
        /// <summary>
        /// 加计数器状态
        /// </summary>
        public bool QU { get {return QU = CV >= PV; } private set { }}
        /// <summary>
        /// 减计数器状态
        /// </summary>
        public bool QD { get { return QD = CV <= 0; } private set { } }
        /// <summary>
        /// 当前计数器值
        /// </summary>
        public int CV { get; private set; }
    }
}
